package net.cloudsun.graph.puzzle.group;

import net.cloudsun.graph.group.FiniteGroup;
import net.cloudsun.graph.puzzle.JigsawState;
import net.cloudsun.graph.puzzle.Pair;
import net.cloudsun.graph.puzzle.PuzzlePosition;
import net.cloudsun.graph.puzzle.relation.SmallAnticlockwiseRotate;
import net.cloudsun.graph.puzzle.relation.SmallClockwiseRotate;
import net.cloudsun.graph.util.ArrayUtils;

import java.util.Comparator;
import java.util.function.Function;

/**
 * puzzle的小旋转群
 * created at 25/11/2021
 *
 * @author 俞建波
 * <a href="mailto://yujianbo@chtwm.com">yujianbo@chtwm.com</a>
 * @since 1.2.0
 */
public class PuzzleSmallRotateGroup extends FiniteGroup<JigsawState> {

    /**
     * 代码
     */
    private String code;
    private PuzzlePosition position;

    /**
     * 群的代码
     *
     * @param position
     */
    public PuzzleSmallRotateGroup(PuzzlePosition position) {
        final Pair<Function<JigsawState, JigsawState>> pair = new Pair<>();
        pair.setA(SmallClockwiseRotate.ofPosition(position));
        pair.setB(SmallAnticlockwiseRotate.ofPosition(position));
        setOperators(pair);
        this.position = position;
    }

    public PuzzleSmallRotateGroup(JigsawState element, PuzzlePosition position) {
        this(position);
        this.code = getCode(element, position);
    }

    /**
     * 0 1 2
     * 3 4 5
     * 6 7 8
     *
     * @param element
     * @param position
     * @return
     */
    private static String getCode(JigsawState element, PuzzlePosition position) {
        int[] ints = ArrayUtils.joinArray(element.toArray());
        switch (position) {
            case TOP_LEFT:
                return "C" + ints[2] + ints[5] + ints[6] + ints[7] + ints[8];
            case TOP_RIGHT:
                return "" + ints[0] + ints[3] + "C" + ints[6] + ints[7] + ints[8];
            case BOTTOM_LEFT:
                return "" + ints[0] + ints[1] + ints[2] + "C" + ints[5] + ints[8];
            case BOTTOM_RIGHT:
                return "" + ints[0] + ints[1] + ints[2] + ints[3] + ints[6] + "C";
        }
        return null;
    }

    @Override
    protected int getMetaIndex(Comparator<? super JigsawState> comparator) {
        if (super.getElements() == null || super.getElements().isEmpty()) {
            return -1;
        }
        int i = 0;
        for (JigsawState jigsawState : super.getElements()) {
            if (isMeta(jigsawState)) {
                return i;
            }
            i += 1;
        }
        return -1;
    }

    private boolean isMeta(JigsawState jigsawState) {
        // 定义一个状态为元的标准是在群里的位置符合范式 1 2 3 4
        // 首先是活动单元的位置
        // 标准就是 1 < 2 < 3 < 4
        final int[][] ints = jigsawState.toArray();
        int[][] sub = activeArrays(ints);
        // 有两种，但是8必须是最后一个
        if (sub[1][1] != 8) {
            return false;
        }

        return (sub[0][0] < sub[0][1] && sub[0][1] < sub[1][0])
                || (sub[0][0] > sub[0][1] && sub[0][1] > sub[1][0]);
    }

    private int[][] activeArrays(int[][] ints) {
        final int[][] result = new int[2][2];
        final int rowStart = this.position.getStartRow();
        final int columStart = this.position.getStartColumn();
        result[0][0] = ints[rowStart][columStart];
        result[0][1] = ints[rowStart][columStart + 1];
        result[1][0] = ints[rowStart + 1][columStart];
        result[1][1] = ints[rowStart + 1][columStart + 1];
        return result;
    }

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }
}
